﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FTPService
{
    using System;
    using System.Collections.Concurrent;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading.Tasks;

    class FtpServer
    {
        private const int Port = 21; // FTP 默认端口
        private TcpListener _listener;
        private readonly ConcurrentDictionary<TcpClient, Task> _clients = new ConcurrentDictionary<TcpClient, Task>();



        public async Task StartAsync()
        {
            _listener = new TcpListener(IPAddress.Any, Port);
            _listener.Start();
            Console.WriteLine($"FTP 服务器已启动，监听端口 {Port}");

            while (true)
            {
                try
                {
                    TcpClient client = await _listener.AcceptTcpClientAsync();
                    Task clientTask = HandleClientAsync(client);
                    _clients.TryAdd(client, clientTask);
                    clientTask.ContinueWith(t => _clients.TryRemove(client, out _));
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"接收客户端连接时发生错误: {ex.Message}");
                }
            }
        }

        private async Task HandleClientAsync(TcpClient client)
        {
            NetworkStream stream = client.GetStream();
            StreamReader reader = new StreamReader(stream, Encoding.ASCII);
            StreamWriter writer = new StreamWriter(stream, Encoding.ASCII) { AutoFlush = true };

            try
            {
                await writer.WriteLineAsync("220 Welcome to High Concurrency FTP Server");

                string line;
                while ((line = await reader.ReadLineAsync()) != null)
                {
                    Console.WriteLine($"收到命令: {line}");
                    string[] command = line.Split(' ');

                    switch (command[0].ToUpper())
                    {
                        case "USER":
                            await writer.WriteLineAsync("331 Username okay, need password.");
                            break;
                        case "PASS":
                            await writer.WriteLineAsync("230 User logged in, proceed.");
                            break;
                        case "PWD":
                            await writer.WriteLineAsync("257 \"/\" is the current directory");
                            break;
                        case "LIST":
                            await writer.WriteLineAsync("150 Opening ASCII mode data connection for file list");
                            await writer.WriteLineAsync("226 Directory send OK");
                            break;
                        case "RETR":
                            await RetrieveFileAsync(command[1], stream, writer);
                            break;
                        case "STOR":
                            await StoreFileAsync(command[1], stream, reader, writer);
                            break;
                        case "QUIT":
                            await writer.WriteLineAsync("221 Goodbye.");
                            client.Close();
                            return;
                        default:
                            await writer.WriteLineAsync("502 Command not implemented");
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理客户端请求时发生错误: {ex.Message}");
            }
            finally
            {
                client.Close();
            }
        }

        private async Task RetrieveFileAsync(string filename, NetworkStream stream, StreamWriter writer)
        {
            string filePath = @"D:\Hangs\Package\B853";
            if (File.Exists(filePath))
            {
                await writer.WriteLineAsync("150 Opening data connection for file transfer");
                byte[] fileData = await Task.Run(() =>
                {
                    return File.ReadAllBytes(filePath);
                });
                await stream.WriteAsync(fileData, 0, fileData.Length);
                await writer.WriteLineAsync("226 Transfer complete");
            }
            else
            {
                await writer.WriteLineAsync("550 File not found");
            }
        }

        private async Task StoreFileAsync(string filename, NetworkStream stream, StreamReader reader, StreamWriter writer)
        {
            string filePath = Path.Combine(Directory.GetCurrentDirectory(), filename);
            await writer.WriteLineAsync("150 Opening data connection for file upload");

            using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
            {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                {
                    await fileStream.WriteAsync(buffer, 0, bytesRead);
                }
            }

            await writer.WriteLineAsync("226 Transfer complete");
        }
    }

}
